﻿/// <reference path="/../rwt.app/g/jquery-vsdoc.js" />

$$.Scroller = function (page) {
    if (!page) return;
    var me = this;
    function scroller(Node) {
    	var my = Node.Scroller = this;
        var JNode = $(Node), Childs = [], Lazy;
        var Horiz = Node.ScrollerX = Node.classList.contains("X");	//横向滚动

        var Follow = Node.getAttribute("scroller-follow") === "true" || false;	//跟随触摸滚动，没有加速和惯性
        function follow(x,y,evt) {
        	if (Horiz === true) Node.scrollLeft -= x;
        	else Node.scrollTop -= y;
        	evt.preventDefault();
        	evt.stopImmediatePropagation();
        	evt.returnValue = false;
        	return true;
        }


        var Pinch = Node.getAttribute("scroller-pinch") === "true" || false;	//双指缩放
        var pinching = false, pinchDist = 0;
        function pinch(touchs)
        {
        	var dist0 = pinchDist;
        	var dist = pinchDist = Math.abs(touchs[0].pageX - touchs[1].pageX) + Math.abs(touchs[0].pageY - touchs[1].pageY);
        	if (!pinching) { pinching = true; return; }
        	if (dist0 <= 0 || (dist -= dist0) === 0) return;
        	JNode.triggerHandler("pinch", dist);
        }


		//最大顶部下拉高度，大于0表示开始监控上顶下拉动作；横向时是左顶右拉
        var PullTop = $$.ParseInt(Node.getAttribute("scroller-pulltop")) || 0;
        var pullToping = 0, pullTopDist = 0;
        function pullTopEnd() {
        	if (pullToping) JNode.triggerHandler("pulltopend", pullTopDist);
        	pullToping = pullTopDist = 0;
        }
        function pullUp(x, y) {
        	if (Node.scrollTop === 0) {
        		if (!pullToping) {
        			if (y <= 0) return;
        			pullToping = 1;
        		}
        	}
        	else if (!pullToping) return;
        	var dist = pullTopDist + y;
        	if (dist <= 0) {
        		if (pullTopDist <= 0) return;
        		pullTopDist = 0;
        	}
        	else if (dist >= PullTop) {
        		if (pullTopDist >= PullTop) return;
        		pullTopDist = PullTop;
        	}
        	else pullTopDist = dist;
        	JNode.triggerHandler("pulltop", dist);
        }
        function pullLeft(x, y) {
        	if (Node.scrollLeft === 0) {
        		if (!pullToping) {
        			if (x <= 0) return;
        			pullToping = 1;
        		}
        	}
        	else if (!pullToping) return;
        	var dist = pullTopDist + x;
        	if (dist <= 0) {
        		if (pullTopDist <= 0) return;
        		pullTopDist = 0;
        	}
        	else if (dist >= PullTop) {
        		if (pullTopDist >= PullTop) return;
        		pullTopDist = PullTop;
        	}
        	else pullTopDist = dist;
        	JNode.triggerHandler("pulltop", dist);
        }
        var pullTop = pullUp;
        if (Horiz) pullTop = pullLeft;


    	//最大底部上拉高度，大于0表示开始监控底部上拉动作；横向时是右顶左拉
        var PullBot = $$.ParseInt(Node.getAttribute("scroller-pullbottom")) || 0;
        //if ($$.IsIOS && PullBot > 10) { PullBot = 10; console.info("PullBot:" + PullBot); }
        var pullBoting = 0, pullBotDist = 0;
        function pullBotEnd() {
        	if (pullBoting) JNode.triggerHandler("pullbottomend", pullBotDist);
        	pullBoting = pullBotDist = 0;
        }
        //function pullDown(x, y) {
        //	var max = Node.scrollHeight - Node.clientHeight - 1;
        //	if (Node.scrollTop >= max) {
        //		if (!pullBoting) {
        //			if (y >= 0) return;
        //			pullBoting = 1;
        //		}
        //	}
        //	else if (!pullBoting) return;
        //	var dist = pullBotDist - y;
        //	if (dist <= 0) {
        //		if (pullBotDist <= 0) return;
        //		pullBotDist = 0;
        //	}
        //	else if (dist >= PullBot) {
        //		if (pullBotDist >= PullBot) return;
        //		pullBotDist = PullBot;
        //	}
        //	else pullBotDist = dist;
        //	JNode.triggerHandler("pullbottom", dist);
        //}
        function pullRight(x, y) {
        	var max = Node.scrollWidth - Node.clientWidth - 1;
        	if (Node.scrollLeft >= max) {
        		if (!pullBoting) {
        			if (x >= 0) return;
        			pullBoting = 1;
        		}
        	}
        	else if (!pullBoting) return;
        	var dist = pullBotDist - x;
        	if (dist <= 0) {
        		if (pullBotDist <= 0) return;
        		pullBotDist = 0;
        	}
        	else if (dist >= PullBot) {
        		if (pullBotDist >= PullBot) return;
        		pullBotDist = PullBot;
        	}
        	else pullBotDist = dist;
        	JNode.triggerHandler("pullbottom", dist);
        }
        var pullBot = function () { };//pullDown;
        if (Horiz) pullBot = pullRight;


		//返回顶部
        var GotopNode = null;   
        if (Node.getAttribute("scroller-gotop") === "true") {
        	GotopNode = $(".gotop", Node.parentNode);
        	if (GotopNode.length < 1) {
        		GotopNode = $("<div>").addClass("gotop").prependTo(Node.parentNode);
        		GotopNode.on("click", function () { JNode.animate({ scrollTop: '0px' }, 500, "linear", goTop); });
        	}
        }
        var GotopShowing = false, GotopShowDist = Math.max(Node.clientHeight, 600);
        function goTop() {
        	if (Node.scrollTop > GotopShowDist) {
        		if (!GotopShowing) { GotopNode.addClass("sel"); GotopShowing = true; }
        	}
        	else if (Node.scrollTop < GotopShowDist) {
        		if (GotopShowing) { GotopNode.removeClass("sel"); GotopShowing = false; }
        	}
        }

		
        var scrolling = 0;//滚动状态：0 停止，1 开始滚动，2 触摸滚动，9 惯性滚动
        function doScrollEnd() {
        	scrolling = 0;
        	my.Move();
        	if (GotopNode) goTop();
        	scrollPos = Horiz ? Node.scrollLeft : Node.scrollTop;
        	JNode.triggerHandler("scrollend");
        }

        var scrollidx = 0;
        var scrollPos = Horiz ? Node.scrollLeft : Node.scrollTop;
        function captureScrollEnd() {
        	scrolling = 9;
        	var scridx = ++scrollidx;
        	var tm = $$.Timer.Loop(function (num) {
        		if (scridx !== scrollidx) {
        			my.Move();
        			$$.Timer.Finish(tm);
        			return;
        		}
        		var pos = Horiz ? Node.scrollLeft : Node.scrollTop;
        		if (pos === scrollPos) return;
        		scrollPos = pos;
        		my.Move();
        	}, 300);
        	my.Move();
        }



        var touchX = 0, touchY = 0;
        if (PullTop || PullBot || Follow || Pinch) JNode.on("touchmove", function (evt) {
        	var touchs = evt.originalEvent.touches;
        	scrolling = 2;
        	if (Pinch) {
        		if (touchs.length > 1) {
        			pinch(touchs);
        			touchX = touchs[0].pageX;
        			touchY = touchs[0].pageY;
        			return;
        		}
        		if (pinching) pinching = false;
        	}

        	var x = touchs[0].pageX, w = x - touchX; touchX = x;
        	var y = touchs[0].pageY, h = y - touchY; touchY = y;

        	if (Horiz === true) {
        		if (!(Math.abs(w) > Math.abs(h))) return;
        	}
        	else {
        		if (!(Math.abs(h) > Math.abs(w))) return;
        	}

        	var f = 0;
        	if (Follow) f = follow(w, h, evt);
        	if (PullTop) pullTop(w, h);
        	if (PullBot) pullBot(w, h);
        	if (f) return false;
        });

        JNode.on("scroll", function (evt) {
        	if (scrolling === 9) doScrollEnd();
        });
        JNode.on("touchstart", function (evt) {
        	var touchs = evt.originalEvent.touches;
        	touchX = touchs[0].pageX;
        	touchY = touchs[0].pageY;
        	scrolling = 1;
        	if (touchs.length > 1) {
        		pinching = false;
        		pinch(touchs);
        	}
        });

        function touchEnd(evt) {
        	if (Pinch) pinching = false;
        	if (Follow) doScrollEnd();
        	else captureScrollEnd();
        	if (PullTop) pullTopEnd();
        	if (PullBot) pullBotEnd();
        };
        JNode.on("touchend", touchEnd);
        JNode.on("touchcancel", touchEnd);


        my.Move = function (only) {
            if (Lazy) Lazy.Move();
            if (only === true) return;
            for (var i in Childs) {
            	Childs[i].Move(true);
            }
        };

        var Hold = null;
        my.Start = function () {
        	Childs = [];
        	var jn = $(".Scroller", Node);
        	for (var i = 0; i < jn.length; i++) {
        		var h = jn[i].Scroller;
        		if(h) Childs.push(h);
        	}

        	if (!Lazy) Lazy = new $$.LazyImager(Node, Horiz);
        	Lazy.Start();

        	if (Hold) return;
        	Hold = $("<div>");
        	if (Horiz) Hold.addClass("ScrollerHoldX");
        	else Hold.addClass("ScrollerHold");
        	Hold.prependTo(Node);
        };
    }


    var Scrollers = [];
    me.Start = function() {
    	Scrollers = [];
    	var jn = $(".Scroller", page.Node);
    	for (var i = jn.length - 1; i >= 0; i--) {
    		if (jn[i].Scroller) Scrollers.push(jn[i].Scroller);
    		else Scrollers.push(new scroller(jn[i]));
    	}

        for (var i in Scrollers) {
        	Scrollers[i].Start();
        }
    };
};

$$.Scroller.KillAppBounce = function () {
	var docbody = document.body, docelem = document.documentElement;
	document.addEventListener("touchmove", function (evt) {
		var n = evt.srcElement;
		while (n) {
			if (n === docbody || n === docelem || n === document) break;
			if (n.classList.contains("Scroller")) return;
			n = n.parentNode;
		}
		console.info("window kill touchmove");
		evt.preventDefault();
		evt.returnValue = false;
		//$$.Tips("window kill touchmove", 1);
		return false;
	}, false);
};